<?php
/**
 * Created by PhpStorm.
 * User: whwyy
 * Date: 2018/3/28 0028
 * Time: 16:50
 */


namespace Validate;

class Validate extends BaseValidator
{
	
	private $validator = [];
	
	/** @var Validate */
	private static $instance;
	
	/**
	 * @var array
	 */
	protected $classMap = [
		'not empty' => [
			'Validate\RequiredValidator',
			[
				'class' => 'Validate\EmptyValidator',
				'method' => EmptyValidator::CAN_NOT_EMPTY
			]
		],
		'not null' => [
			'Validate\RequiredValidator',
			[
				'class' => 'Validate\EmptyValidator',
				'method' => EmptyValidator::CAN_NOT_NULL
			]
		],
		'required' => 'Validate\RequiredValidator',
		'datetime' => [
			'class' => 'Validate\DatetimeValidator',
			'method' => DateTimeValidator::DATE_TIME
		],
		'date' => [
			'class' => 'Validate\DatetimeValidator',
			'method' => DateTimeValidator::DATE
		],
		'time' => [
			'class' => 'Validate\DatetimeValidator',
			'method' => DateTimeValidator::TIME
		],
		'timestamp' => [
			'class' => 'Validate\DatetimeValidator',
			'method' => DateTimeValidator::STR_TO_TIME
		],
		'maxLength' => [
			'class' => 'Validate\LengthValidator',
			'method' => 'max',
		],
		'minLength' => [
			'class' => 'Validate\LengthValidator',
			'method' => 'min',
		],
		'email' => [
			'class' => 'Validate\EmailValidator',
			'method' => 'email',
		],
		'length' => [
			[
				'class' => 'Validate\LengthValidator',
				'method' => 'min',
			],
			[
				'class' => 'Validate\LengthValidator',
				'method' => 'max',
			]
		]
	];
	
	/**
	 * @param $options
	 * @throws \ReflectionException
	 */
	public function make($options, $data = [])
	{
		foreach ($options as $key => $val) {
			$value = explode('|', $val);
			if (empty($value)) {
				continue;
			}
			foreach ($value as $_key => $_val) {
				$this->write($key, $_val, $data);
			}
		}
	}
	
	/**
	 * @return Validate
	 */
	public static function getInstance()
	{
		if (static::$instance instanceof Validate) {
			return static::$instance;
		}
		static::$instance = new Validate();
		return static::$instance;
	}
	
	/**
	 * @param $value
	 * @throws \ReflectionException
	 */
	private function write($key, $_val, $data)
	{
		$param['field'] = $key;
		$param['rules'] = $_val;
		$param['params'] = $data;
		if (strpos($_val, '=')) {
			$_value = explode('=', $_val);
			if (count($_value) != 2) {
				return;
			}
			$param['rules'] = $_value[0];
			$param['value'] = $_value[1];
		}
		$class = $this->classMap[$param['rules']] ?? null;
		if (empty($class)) {
			return;
		}
		$this->createValidator($class, $param);
	}
	
	/**
	 * @param $class
	 * @throws \ReflectionException
	 */
	private function createValidator($class, $param)
	{
		if (is_array($class)) {
			if (isset($class['class'])) {
				$reflect = new \ReflectionClass($class['class']);
				unset($class['class']);
				
				$param = array_merge($param, $class);
			} else {
				foreach ($class as $key => $val) {
					$this->createValidator($val, $param);
				}
			}
		} else if (is_string($class)) {
			$reflect = new \ReflectionClass($class);
		}
		if (isset($reflect)) {
			$object = $reflect->newInstanceArgs([$param]);
			
			if (!empty($object)) {
				array_push($this->validator, $object);
			}
		}
	}
	
	/**
	 * @return bool
	 */
	public function validator()
	{
		if (empty($this->validator)) {
			return true;
		}
		foreach ($this->validator as $key => $val) {
			if (empty($val)) {
				continue;
			}
			if (!$val->trigger()) {
				$this->message = $val->getError();
				return false;
			}
		}
		return true;
	}
	
}